package com.wx.spring.ioc.parsing;

import com.wx.spring.constant.ErrInfo;
import com.wx.spring.exception.XmlException;
import com.wx.spring.ioc.IocContainer;
import com.wx.spring.ioc.factory.ChildBeanDefinition;
import com.wx.spring.ioc.factory.GenericBeanDefinition;
import com.wx.spring.ioc.rules.IocXmlRules;
import com.wx.spring.utils.EnumsUtils;
import com.wx.spring.utils.MyStringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.dom4j.DocumentException;
import org.dom4j.Element;

import java.util.ArrayList;
import java.util.List;

import static com.wx.spring.constant.ErrInfo.COMMON_RESOURCE_FORMAT_ERROR;
import static com.wx.spring.constant.ResourcesSuffix.XML_RESOURCES;

/**
 * @author wx
 * @Description: 解析xml资源中的bean
 * @date 2019/1/11 001111:27
 */
@Slf4j
public class ParsingResourcesXmlBean implements ParsingResources {

    /**
     * @param contextConfigLocation
     * @description: 解析xml bean内容到xmlBeanMap容器中
     * @author: wx
     * @date: 2019/1/11 0011
     * @return: void
     */
    @Override
    public void parsingContent(String contextConfigLocation) throws DocumentException {
        //验证资源路径是否为空与是否合法
        if (MyStringUtils.isBlank(contextConfigLocation)) {
            throw new NullPointerException(ErrInfo.ParsingResourcesXmlBeanErrInfo.RESOURCE_PATH_IS_NULL);
        }
        if (!contextConfigLocation.endsWith(XML_RESOURCES)) {
            throw new XmlException(ErrInfo.ParsingResourcesXmlBeanErrInfo.RESOURCE_PATH_ILLEGAL);
        }
        //根元素下面的所有子元素
        List<Element> elementsList = getXmlElements(contextConfigLocation);
        if (CollectionUtils.isEmpty(elementsList)) {
            return;
        }

        for (Element element : elementsList) {
            //如果子元素是bean
            if (IocXmlRules.BEAN_RULE.getType().equals(element.getName())) {
                //声明一个bean的map,用来盛放当前bean子元素的容器
                GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
                List<ChildBeanDefinition> childBeanDefinitionList = new ArrayList<>();
                //获取bean元素的id属性与class属性的值
                String beanId = element.attributeValue(IocXmlRules.BEAN_RULE.getName());
                String beanClass = element.attributeValue(IocXmlRules.BEAN_RULE.getValue());
                if (MyStringUtils.isNotBlankMore(beanId, beanClass)) {
                    //设置class属性的值
                    genericBeanDefinition.setClassName(beanClass);
                    //获取当前bean的所有子元素
                    List<Element> elements = element.elements();
                    if (CollectionUtils.isEmpty(elements)) {
                        log.info("{}下面没有子元素", beanId);
                        continue;
                    }
                    for (Element childrenElement : elements) {
                        //根据子元素名称匹配注入规则,set or 构造器
                        IocXmlRules rulesEnum = EnumsUtils.getRulesEnum(IocXmlRules.class, childrenElement.getName());
                        if (rulesEnum == null) {
                            continue;
                        }
                        ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition();
                        childBeanDefinition.setType(rulesEnum.getType());
                        //元素下的属性name
                        String name = rulesEnum.getName();
                        //元素下的属性value
                        String value = rulesEnum.getValue();
                        //设置对象属性
                        setChildBeanDefinitionByType(childrenElement, childBeanDefinition, name, value, childBeanDefinitionList);

                    }
                    genericBeanDefinition.setChildBeanDefinitionList(childBeanDefinitionList);
                    //设置进map
                    IocContainer.getXmlBeanMap().put(beanId, genericBeanDefinition);
                }
            }
        }

    }

    /**
     * @param element
     * @param childBeanDefinition
     * @param name
     * @param value
     * @param childBeanDefinitionList
     * @description: 设置对象属性
     * @author: wx
     * @date: 2019/1/11 0011
     * @return: void
     */
    private void setChildBeanDefinitionByType(Element element, ChildBeanDefinition childBeanDefinition, String name, String value, List<ChildBeanDefinition> childBeanDefinitionList) {
        if (childBeanDefinition != null) {
            //设置元素下name属性的值
            childBeanDefinition.setAttributeOne(element.attributeValue(name));
            //设置元素下的value属性的值
            childBeanDefinition.setAttributeTwo(element.attributeValue(value));
            childBeanDefinitionList.add(childBeanDefinition);

        } else {
            throw new XmlException(COMMON_RESOURCE_FORMAT_ERROR);
        }

    }

}
